home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / IndiZone / vroom / collision.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  9.8 KB  |  498 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <stdio.h>
  18. #include <math.h>
  19.  
  20. #include "vroom.h"
  21. #include "car.h"
  22. #include "ogl.h"
  23. #include "track.h"
  24. #include "collision.h"
  25. #include "sound.h"
  26.  
  27. #define    RF    0
  28. #define    LF    1
  29. #define    LR    2
  30. #define    RR    3
  31.  
  32.  
  33. /* BEGIN PROTOTYPES -S collision.c */
  34. static void     carsCollided( int i, int j ) ;
  35. static int      checkLineWithLine( vec2 r0, vec2 r1, vec2 r2, vec2 r3 ) ;
  36. static int      checkRectWithRect( vec2 a[4], vec2 b[4] ) ;
  37. static void     mapCarCoords( int n, vec2 v[4] ) ;
  38. /* END PROTOTYPES -S collision.c */
  39.  
  40.  
  41. float            collisionRadius2 ;
  42.  
  43. extern int        nTracks ;
  44. extern int        nPlayers ;
  45. extern int        debugOn ;
  46. extern int        self ;
  47. extern int        isRobot[] ;
  48. extern int        updateStatWindow ;
  49. extern float        carLength ;
  50. extern float        carWidth ;
  51. extern Track        *introTrack[] ;
  52. extern PlayerStruct    player[] ;
  53. extern Car        cars[MAX_PLAYERS] ;
  54. extern Sfx        collideSfx ;
  55.  
  56.  
  57. /*------------------------------------------------------------------------------
  58.  * Collision detection.
  59.  *----------------------------------------------------------------------------*/
  60. void
  61. checkCollisions(
  62.     void
  63.     )
  64. {
  65.     int    i ;
  66.     int    j ;
  67.     int    iMapped ;
  68.     int    mapped[MAX_PLAYERS] ;
  69.     float    x ;
  70.     float    y ;
  71.     float    dx ;
  72.     float    dy ;
  73.     float    trackLen ;
  74.     vec2    v[MAX_PLAYERS][4] ;
  75.  
  76.     mapped[0] = 0 ;
  77.     mapped[1] = 0 ;
  78.     mapped[2] = 0 ;
  79.     mapped[3] = 0 ;
  80.     mapped[4] = 0 ;
  81.     mapped[5] = 0 ;
  82.     mapped[6] = 0 ;
  83.     mapped[7] = 0 ;
  84.  
  85.     trackLen = (float)nTracks ;
  86.  
  87.     for( i = 0 ; i < ( MAX_PLAYERS - 1 ) ; i++ )
  88.     {
  89.         if( !CAR_RACING( cars+i ) )
  90.         {
  91.             continue ;
  92.         }
  93.         x = cars[i].x ;
  94.         y = cars[i].y ;
  95.         for( j = i + 1 ; j < MAX_PLAYERS ; j++ )
  96.         {
  97.             if( !CAR_RACING( cars+j ) )
  98.             {
  99.                 continue ;
  100.             }
  101.             dx = x - cars[j].x ;
  102.             dy = y - cars[j].y ;
  103.             if( dx * dx + dy * dy < collisionRadius2 )
  104.             {
  105.                 if( !mapped[i] )
  106.                 {
  107.                     mapCarCoords( i, v[i] ) ;
  108.                 }
  109.                 if( !mapped[j] )
  110.                 {
  111.                     mapCarCoords( j, v[j] ) ;
  112.                 }
  113.                 if( checkRectWithRect( v[i], v[j] ) )
  114.                 {
  115.                     carsCollided( i, j ) ;
  116.                 }
  117.             }
  118.         }
  119.     }
  120. }
  121.  
  122.  
  123.  
  124. /*------------------------------------------------------------------------------
  125.  * Map the corner points of a car.
  126.  *----------------------------------------------------------------------------*/
  127. static void
  128. mapCarCoords(
  129.     int    n,
  130.     vec2    v[4]
  131.     )
  132. {
  133.     float    xc ;
  134.     float    yc ;
  135.     float    h ;
  136.     float    wc ;
  137.     float    ws ;
  138.     float    lc ;
  139.     float    ls ;
  140.  
  141.     xc = cars[n].x ;
  142.     yc = cars[n].y ;
  143.  
  144.     h = cars[n].theta ;
  145.  
  146.     wc = 0.5f * cosf( h ) ;
  147.     ws = 0.5f * sinf( h ) ;
  148.  
  149.     lc = carLength * wc ;
  150.     ls = carLength * ws ;
  151.  
  152.     wc *= carWidth ;
  153.     ws *= carWidth ;
  154.  
  155.     v[RF][0] = xc + wc - ls ;
  156.     v[RF][1] = yc + ws + lc ;
  157.  
  158.     v[LF][0] = xc - wc - ls ;
  159.     v[LF][1] = yc - ws + lc ;
  160.  
  161.     v[RR][0] = xc + wc + ls ;
  162.     v[RR][1] = yc + ws - lc ;
  163.  
  164.     v[LR][0] = xc - wc + ls ;
  165.     v[LR][1] = yc - ws - lc ;
  166. }
  167.  
  168.  
  169.  
  170. /*------------------------------------------------------------------------------
  171.  * Check if two rectangles overlap.
  172.  *----------------------------------------------------------------------------*/
  173. static int
  174. checkRectWithRect(
  175.     vec2    a[4],
  176.     vec2    b[4]
  177.     )
  178. {
  179.     int    a0 ;
  180.     int    a1 ;
  181.     int    b0 ;
  182.     int    b1 ;
  183.  
  184.     for( a0 = 0 ; a0 < 4 ; a0++ )
  185.     {
  186.         a1 = ( a0 + 1 ) % 4 ;
  187.         for( b0 = 0 ; b0 < 4 ; b0++ )
  188.         {
  189.             b1 = ( b0 + 1 ) % 4 ;
  190.             if( checkLineWithLine( a[a0], a[a1], b[b0], b[b1] ) )
  191.             {
  192.                 return( 1 ) ;
  193.             }
  194.         }
  195.     }
  196.  
  197.     return( 0 ) ;
  198. }
  199.  
  200.  
  201.  
  202. /*------------------------------------------------------------------------------
  203.  * Check for the intersection of two lines.  One line is defined by the
  204.  * points r0 and r1; the other line is defined by the points r2 and r3.
  205.  *
  206.  * Line 1 is defined by:    Pt = r0 + s * ( r1 - r0 ) ;    0 <= s <= 1
  207.  * Line 2 is defined by:    Pt = r2 + t * ( r3 - r2 ) ;    0 <= t <= 1
  208.  *
  209.  * Set the two equal, solve for s and t.  If s and t are both between
  210.  * 0 and 1 (inclusive), the lines intersect.  Return 1 if the lines
  211.  * intersect, 0 otherwise.
  212.  *----------------------------------------------------------------------------*/
  213. static int
  214. checkLineWithLine(
  215.     vec2    r0,
  216.     vec2    r1,
  217.     vec2    r2,
  218.     vec2    r3
  219.     )
  220. {
  221.     float    denom ;
  222.     float    denom1 ;
  223.     float    denom2 ;
  224.     float    ns, nt ;
  225.     float    dx10 ;
  226.     float    dy10 ;
  227.     float    dx20 ;
  228.     float    dy20 ;
  229.     float    dx32 ;
  230.     float    dy32 ;
  231.  
  232.     dx10 = r1[0] - r0[0] ;
  233.     dy10 = r1[1] - r0[1] ;
  234.  
  235.     dx20 = r2[0] - r0[0] ;
  236.     dy20 = r2[1] - r0[1] ;
  237.  
  238.     dx32 = r3[0] - r2[0] ;
  239.     dy32 = r3[1] - r2[1] ;
  240.  
  241.     denom1 = dy10 * dx32 ;
  242.     denom2 = dx10 * dy32 ;
  243.  
  244.     /*
  245.      * Fail if lines are parallel.
  246.      */
  247.     if( denom1 == denom2 )
  248.     {
  249.         return( 0 ) ;
  250.     }
  251.  
  252.     denom = denom1 - denom2 ;
  253.  
  254.     ns = dx32 * dy20 - dy32 * dx20 ;
  255.     nt = dx10 * dy20 - dy10 * dx20 ;
  256.  
  257.     /*
  258.      * Fail if s or t are less than 0 (negative, which happens if ns or nt
  259.      * are of different signs than denom) or greater than 1 (if abs(ns) or
  260.      * abs(nt) are greater than abs(denom) ).
  261.      */
  262.     if( denom < 0 )
  263.     {
  264.         if( ns > 0 || nt > 0 || ns < denom || nt < denom )
  265.         {
  266.             return( 0 ) ;
  267.         }
  268.     }
  269.     else
  270.     {
  271.         if( ns < 0 || nt < 0 || ns > denom || nt > denom )
  272.         {
  273.             return( 0 ) ;
  274.         }
  275.     }
  276.     return( 1 ) ;
  277. }
  278.  
  279.  
  280.  
  281. /*------------------------------------------------------------------------------
  282.  * Two cars collided.
  283.  *----------------------------------------------------------------------------*/
  284. static void
  285. carsCollided(
  286.     int    i,
  287.     int    j
  288.     )
  289. {
  290.     int    n ;
  291.     int    k ;
  292.     vec2    a ;
  293.     vec2    b ;
  294.     float    dx ;
  295.     float    dy ;
  296.     float    bs ;
  297.     float    theta ;
  298.     float    angle ;
  299.     float    s ;
  300.     float    len ;
  301.  
  302.     /*
  303.      * First check if cars had vastly different headings.  If so, this
  304.      * probably means that they collided at a track crossing, so both
  305.      * cars should wreck.
  306.      */
  307.     theta = player[i].headingDeg - player[j].headingDeg ;
  308.     if( theta < -15.0f || theta > 15.0f )
  309.     {
  310.         a[0] = -cosf( cars[i].theta ) ;
  311.         a[1] = -sinf( cars[i].theta ) ;
  312.         wipeOutCar( &(cars[i]), a[0], a[1], ( theta > 0.0f ),
  313.                 WIPE_OUT_COLLISION );
  314.         wipeOutCar( &(cars[j]), a[0], a[1], ( theta < 0.0f ),
  315.                 WIPE_OUT_COLLISION );
  316.         theta = fmodf( theta + 720.0f, 360.0f ) - 180.0f ;
  317.         if( ABSFUNC( theta ) < 90.0f )
  318.         {
  319.             if( isRobot[i] )
  320.             {
  321.                 if( isRobot[j] && ( rand() % 2 ) == 1 )
  322.                 {
  323.                     cars[j].headOn = 1 ;
  324.                 }
  325.                 else
  326.                 {
  327.                     cars[i].headOn = 1 ;
  328.                 }
  329.             }
  330.             else if( isRobot[j] )
  331.             {
  332.                 cars[j].headOn = 1 ;
  333.             }
  334.         }
  335.         return ;
  336.     }
  337.     dx = cars[i].x - cars[j].x ;
  338.     dy = cars[i].y - cars[j].y ;
  339.     theta = atan2f( dy, dx ) ;
  340.     angle = theta - 0.5f * ( cars[i].theta + cars[j].theta ) ;
  341.     angle *= 180.0f / (float)M_PI ;
  342.     angle = fmodf( angle + 720.0f, 360.0f ) ;
  343.     k = -1 ;
  344.     /*
  345.      * Car i/j bumped by j/i from behind.
  346.      */
  347.     if( ( 85.0f <= angle && angle <= 95.0f ) ||
  348.         ( 265.0f <= angle && angle <= 275.0f ) )
  349.     {
  350.         s = cars[i].speed ;
  351.         cars[i].speed = cars[j].speed ;
  352.         cars[j].speed = s ;
  353.  
  354.         s = 1.1f * carLength - sqrtf( dx * dx + dy * dy ) ;
  355.         n = ( angle < 180.0f ) ? i : j ;
  356.         if( cars[n].speed > 0.0f )
  357.         {
  358.             cars[n].track->follow( cars[n].track,
  359.                     &(cars[n]), s / cars[n].speed ) ;
  360.         }
  361.         else
  362.         {
  363.             cars[n].speed = 0.1f * TOP_SPEED ;
  364.             cars[n].track->follow( cars[n].track,
  365.                     &(cars[n]), s / cars[n].speed ) ;
  366.             cars[n].speed = 0.0f ;
  367.         }
  368.         updatePlayerView( n ) ;
  369.         n = ( i ^ j ) ^ n ;
  370.         cars[n].speed *= 0.75f ;
  371.     }
  372.     /*
  373.      * Car i side swiped from left/right rear by j.
  374.      */
  375.     else if( angle < 180.0f )
  376.     {
  377.         s = 0.5f * ( cars[i].speed + cars[j].speed ) ;
  378.         n = randomChoice( s / TOP_SPEED ) ;
  379.         if( n )
  380.         {
  381.             angle = 90.0f - angle ;
  382.             if( randomChoice( ABSFUNC( angle ) / 180.0f ) )
  383.             {
  384.                 k = j ;
  385.             }
  386.             else
  387.             {
  388.                 k = i ;
  389.             }
  390.         }
  391.         else
  392.         {
  393.             cars[i].status &= ~(CHANGE_LANE_RIGHT |
  394.                 CHANGE_LANE_LEFT) ;
  395.             cars[j].status &= ~(CHANGE_LANE_RIGHT |
  396.                 CHANGE_LANE_LEFT) ;
  397.             if( angle < 90.0f )
  398.             {
  399.                 cars[i].status |= CHANGE_LANE_RIGHT ;
  400.                 cars[j].status |= CHANGE_LANE_LEFT ;
  401.             }
  402.             else
  403.             {
  404.                 cars[i].status |= CHANGE_LANE_LEFT ;
  405.                 cars[j].status |= CHANGE_LANE_RIGHT ;
  406.             }
  407.         }
  408.     }
  409.     /*
  410.      * Car j side swiped from left/right rear by i.
  411.      */
  412.     else
  413.     {
  414.         s = 0.5f * ( cars[i].speed + cars[j].speed ) ;
  415.         n = randomChoice( s / TOP_SPEED ) ;
  416.         if( n )
  417.         {
  418.             angle = 270.0f - angle ;
  419.             if( randomChoice( ABSFUNC( angle ) / 180.0f ) )
  420.             {
  421.                 k = i ;
  422.             }
  423.             else
  424.             {
  425.                 k = j ;
  426.             }
  427.         }
  428.         else
  429.         {
  430.             cars[i].status &= ~(CHANGE_LANE_RIGHT |
  431.                 CHANGE_LANE_LEFT) ;
  432.             cars[j].status &= ~(CHANGE_LANE_RIGHT |
  433.                 CHANGE_LANE_LEFT) ;
  434.             if( angle > 270.0f )
  435.             {
  436.                 cars[i].status |= CHANGE_LANE_RIGHT ;
  437.                 cars[j].status |= CHANGE_LANE_LEFT ;
  438.             }
  439.             else
  440.             {
  441.                 cars[i].status |= CHANGE_LANE_LEFT ;
  442.                 cars[j].status |= CHANGE_LANE_RIGHT ;
  443.             }
  444.         }
  445.     }
  446.  
  447.     if( k == i )
  448.     {
  449.         a[0] = cosf( theta ) ;
  450.         a[1] = sinf( theta ) ;
  451.         cars[i].x += a[0] * carLength ;
  452.         cars[i].y += a[1] * carLength ;
  453.         wipeOutCar( &(cars[i]), a[0], a[1], ( angle < 90.0f ),
  454.                 WIPE_OUT_COLLISION );
  455.         if( j == self )
  456.         {
  457.             sfxPlay( collideSfx ) ;
  458.         }
  459.         cars[j].status |= CAR_BUMP ;
  460.         if( cars[j].status & ( CHANGE_LANE_LEFT |
  461.             CHANGE_LANE_RIGHT ) != 0 )
  462.         {
  463.             cars[j].status ^= CHANGE_LANE_LEFT |
  464.                     CHANGE_LANE_RIGHT ;
  465.         }
  466.     }
  467.     else if( k == j )
  468.     {
  469.         a[0] = -cosf( theta ) ;
  470.         a[1] = -sinf( theta ) ;
  471.         wipeOutCar( &(cars[j]), a[0], a[1], ( angle > 270.0f ),
  472.                 WIPE_OUT_COLLISION ) ;
  473.         if( i == self )
  474.         {
  475.             sfxPlay( collideSfx ) ;
  476.         }
  477.         cars[i].status |= CAR_BUMP ;
  478.         if( cars[i].status & ( CHANGE_LANE_LEFT |
  479.             CHANGE_LANE_RIGHT ) != 0 )
  480.         {
  481.             cars[i].status ^= CHANGE_LANE_LEFT |
  482.                     CHANGE_LANE_RIGHT ;
  483.         }
  484.     }
  485.     else
  486.     {
  487.         cars[i].status |= CAR_BUMP ;
  488.         cars[j].status |= CAR_BUMP ;
  489.         if( i == self || j == self )
  490.         {
  491.             sfxPlay( collideSfx ) ;
  492.         }
  493.     }
  494. }
  495.  
  496.  
  497.  
  498.